import pygame
import random
import copy
import sys
import time
import os
import crop
import bombfile
import expandfile
import rabbit
import rabbitScoreboard
import mason
import masonScoreboard
import powerupscoreboard
import timerScoreboard
import wallSection
import scoreboard
import gameMessage
import jumpfile
from pygame.locals import *
from pygame.mask import from_surface
from math import *
from defs import *

"""
code:
collide_mask was taken from the Pygame 1.9.1 source code.
This was included because version before 1.8.0 did not have this function
and it was needed for our implementation

sfx:
splat taken from http://free-loops.com/download-free-loop-4080.html via Creative Commons search
crash taken from http://free-loops.com/download-free-loop-6774.html via Creative Commons search
"""
def collide_mask(left, right):
   """
   collision detection between two sprites, using masks.
   pygame.sprite.collide_mask(SpriteLeft, SpriteRight): bool

   Tests for collision between two sprites, by testing if
   thier bitmasks overlap. If the sprites have a "mask"
   attribute, that is used as the mask, otherwise a mask is
   created from the sprite image. Intended to be passed as
   a collided callback function to the *collide functions.
   Sprites must have a "rect" and an optional "mask"
   attribute.

   New in pygame 1.8.0
   """
   
   xoffset = right.rect[0] - left.rect[0]
   yoffset = right.rect[1] - left.rect[1]
   try:
      leftmask = left.mask
   except AttributeError:
      leftmask = from_surface(left.image)
   try:
      rightmask = right.mask
   except AttributeError:
      rightmask = from_surface(right.image)
   return leftmask.overlap(rightmask, (xoffset, yoffset))

def pause_temp():
   time.sleep(1)

#def reset(render, walls, crops, masonPlayer, rabbitPlayer, masonScorebrd, rabbitScorebrd):
   #pause_temp()
   

def main():
   # initialise pygame
   pygame.init()
   pygame.mixer.init(44100)
   score = 0
   trailCounter = 0
   player1Mason = True
   player1Score = 0
   player2Score = 0
   
   fileLocation = os.path.join('audio','splat.wav')
   splat = pygame.mixer.Sound(fileLocation)
   
   fileLocation = os.path.join('audio','crash.wav')
   crash = pygame.mixer.Sound(fileLocation)

   # Create a new window
   screen = pygame.display.set_mode(SCREENRECT.size, WINFLAGS)
   pygame.display.set_caption("Keep the Rabbits Out!")

   #Display title screen until player wants to play
   fileLocation = os.path.join('art','title01.jpg')
   background = pygame.image.load(fileLocation)
   screen.blit(background, (0,0))
   pygame.display.update()

   #display title screen for 5 seconds
   pygame.time.wait(5000)
   
   #Display Instructions screen until player wants to play
   fileLocation = os.path.join('art','InstructionsPage.png')
   background = pygame.image.load(fileLocation)
   screen.blit(background, (0,0))
   pygame.display.update()

   #display Instructions screen for 8 seconds
   pygame.time.wait(8000) 
      
   # Create a star map om the background
   #background = pygame.Surface(SCREENRECT.size)
   #background.fill(BLACK)
   fileLocation = os.path.join('art','background.png')
   background = pygame.image.load(fileLocation)

   # copy the background onto the screen
   screen.blit(background, (0,0))
   # the screen is double buffered
   # changes will not appear until we update:
   pygame.display.update()

   # initialize our starting sprites
   # Initialize sprite groups
   render = pygame.sprite.OrderedUpdates()
   
   endGameScreen = False
   
   timerScorebrd = timerScoreboard.TimerScoreboard()
   
   while True:
      render.empty()
      
      pressAnyKeyMessage = gameMessage.GameMessage()
      pressAnyKeyMessage.message = 'Press any key to start the game'
      pressAnyKeyMessage.isCentre = False
      render.add(pressAnyKeyMessage)
      
      if (endGameScreen):
         if (player1Mason):
            player1Score += masonScorebrd.score
            player2Score += rabbitScorebrd.score
         else:
            player1Score += rabbitScorebrd.score
            player2Score += masonScorebrd.score
         #masonScorebrd.score += rabbitScorebrd.score
         
         player1Mason = not player1Mason
         
         timerScorebrd.currentTime = TIMER_LIMIT
      
         pressAnyKeyMessage.isCentre = False
         
         endGameMessage = gameMessage.GameMessage()
         
         if (timerScorebrd.currentRound > NROUNDS):
            endGameMessage.message = 'Final Scores'
         else:
            endGameMessage.message = 'After round ' + str(timerScorebrd.currentRound - 1) + ' (swapping roles)'
         endGameMessage.isTop = True
         render.add(endGameMessage)
         
         player1ScoreMessage = gameMessage.GameMessage()
         player1ScoreMessage.message = 'Player 1: ' + str(player1Score)
         player1ScoreMessage.isLeft = True
         render.add(player1ScoreMessage)
         player2ScoreMessage = gameMessage.GameMessage()
         player2ScoreMessage.message = 'Player 2: ' + str(player2Score)
         player2ScoreMessage.isRight = True
         render.add(player2ScoreMessage)
      else:
         pressAnyKeyMessage.isCentre = True
         
      # update the sprites
      render.update()

      # draw the scene
      render.clear(screen, background)
      render.draw(screen)
      pygame.display.update()
      
      dontStart = True
      while dontStart:
      
         if (timerScorebrd.currentRound > NROUNDS):
            timerScorebrd.currentRound = 1
            player1Mason = True
            player1Score = 0
            player2Score = 0
         
         for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
               return
            elif (event.type == KEYDOWN):
               pressAnyKeyMessage.kill()
               if (endGameScreen):
                  endGameMessage.kill()
                  player1ScoreMessage.kill()
                  player2ScoreMessage.kill()
               
               dontStart = False
      
      crops = pygame.sprite.Group()
      for i in range(0,NCROPS):
         singleCrop = crop.Crop()
         render.add(singleCrop)
         crops.add(singleCrop)
         
      jumps = pygame.sprite.Group()
      # for i in range(0,NJUMPS):
         # singleJump = jumpfile.Jump()
         # render.add(singleJump)
         # jumps.add(singleJump)
	 
      bombs = pygame.sprite.Group()
      # for i in range(0, NBOMBS):
         # singleBomb = bombfile.Bomb()
         # render.add(singleBomb)
         # bombs.add(singleBomb)
      
      expands = pygame.sprite.Group()
      # for i in range(0, NEXPANDS):
         # singleExpand = expandfile.Expand()
         # render.add(singleExpand)
         # expands.add(singleExpand)
   
      rabbitPlayer = rabbit.Rabbit()
      render.add(rabbitPlayer)
       
      masonPlayer = mason.Mason()
      render.add(masonPlayer)
      
      scorebrdBack = scoreboard.Scoreboard()
      render.add(scorebrdBack)
      
      powerupScorebrd = powerupscoreboard.PowerupScoreboard()
      render.add(powerupScorebrd)

      # Create some asteroids
      walls = pygame.sprite.Group()
      tatemp = [0,0,0,0,0,0,0,0,0,0]
      rabbitScorebrd = rabbitScoreboard.RabbitScoreboard()
      render.add(rabbitScorebrd)
      masonScorebrd = masonScoreboard.MasonScoreboard()
      render.add(masonScorebrd)
      
      render.add(timerScorebrd)

      index = 0
      jump = 0
      poweruplimit = 0
      powerup = 0
      jumpCount = 0
      index2 = 0
      on = 1
      indexflag = 0
      
      tatemp2 = pygame.sprite.Group()
      clock = pygame.time.Clock()

      slowflag = 1
      slowcounter = 20
      
      timer = 3
      while (timer > 0):
         gameMessages = gameMessage.GameMessage()
         gameMessages.message = 'Starting game in ' + str(timer)
         render.add(gameMessages)
         
         # update the sprites
         render.update()

         # draw the scene
         render.clear(screen, background)
         render.draw(screen)
         pygame.display.update()
         
         gameMessages.kill()
         
         pause_temp()
         timer -= 1
         
      gameMessages.message = 'Go!!!'
      render.add(gameMessages)
      
      # update the sprites
      render.update()

      # draw the scene
      render.clear(screen, background)
      render.draw(screen)
      pygame.display.update()
      
      pause_temp()

      #while (scorebrd.lives > 0 and scorebrd.walls > 0):
      currTimeCounter = 0
      currTime = 0
      masonDied = False
      while True:
         clock.tick(FPS)
         
         currTimeCounter += clock.get_rawtime()
         
         rabbitPlayer.changeImageCounter()
         
         gameMessages.kill()
         
         powerupScorebrd.setRightPos(rabbitScorebrd.rect.left - 10, rabbitScorebrd.rect.centery)
         
         if (currTimeCounter >= 1000):
            print currTime
            currTime += 1
            currTimeCounter = 0
            timerScorebrd.currentTime -= 1
            
            if (timerScorebrd.currentTime == 0):
               gameMessages = gameMessage.GameMessage()
               gameMessages.message = 'Times Up!'
               render.add(gameMessages)
               # update the sprites
               render.update()

               # draw the scene
               render.clear(screen, background)
               render.draw(screen)
               pygame.display.update()
               
               pause_temp()
               pause_temp()
               gameMessages.kill()
               break
         
         # update the sprites
         render.update()

         # draw the scene
         render.clear(screen, background)
         render.draw(screen)
         pygame.display.update()
         
         #print randomNum
         numPowerups = len(jumps) + len(bombs) + len(expands)
         if (numPowerups < 3):
            randomNum = random.random()
            
            if (randomNum >= POWERUPPERCENTAGE):
               randomPowerup = random.random()
               
               #print randomPowerup
               # if (randomPowerup == JUMP):
                  # singleJump = jumpfile.Jump()
                  # render.add(singleJump)
                  # jumps.add(singleJump)
               # elif (randomPowerup == BOMB):
                  # singleBomb = bombfile.Bomb()
                  # render.add(singleBomb)
                  # bombs.add(singleBomb)
               # elif (randomPowerup == EXPAND):
                  # singleExpand = expandfile.Expand()
                  # render.add(singleExpand)
                  # expands.add(singleExpand)
               if (randomPowerup < 0.5): # < 50%
                  singleJump = jumpfile.Jump()
                  render.add(singleJump)
                  jumps.add(singleJump)
               elif (randomPowerup >= 0.5) and (randomPowerup < 0.8): # 50-80%
                  singleBomb = bombfile.Bomb()
                  render.add(singleBomb)
                  bombs.add(singleBomb)
               elif (randomPowerup >= 0.8): # > 80%
                  singleExpand = expandfile.Expand()
                  render.add(singleExpand)
                  expands.add(singleExpand)
            
         #get events
         for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
               return

         # handle player actions
         keystate = pygame.key.get_pressed()

         #if (keystate[K_UP]):
            # do nothing
         
         if (keystate[K_SPACE] and jump == 0 and rabbitScorebrd.jump > 0):
            jump = 1
            jumpCount = 0
            rabbitScorebrd.jump -= 1
            
            if (powerup == BOMB):
               poweruplimit = 2
            elif (powerup == JUMP):
               poweruplimit = 30
            elif (powerup == EXPAND):
               poweruplimit = 60
               rabbitPlayer.expand()
            
         direction = keystate[K_RIGHT] - keystate[K_LEFT]
         if (direction != 0):
            if (player1Mason):
               rabbitPlayer.turn(direction)
            else:
               masonPlayer.turn(direction)
         
         direction = keystate[K_d] - keystate[K_a]
         if (direction != 0):
            if (player1Mason):
               masonPlayer.turn(direction)
            else:
               rabbitPlayer.turn(direction)

         # detect collisions		

         for singleCrop in crops:
            if (collide_mask(rabbitPlayer,singleCrop)):
               singleCrop.kill()
               rabbitScorebrd.score += 1
         
         for singleJump in jumps:
            if (collide_mask(rabbitPlayer,singleJump)):
               powerupScorebrd.setColour(singleJump.colour)
               singleJump.kill()
               rabbitScorebrd.jump = 1
               powerup = JUMP
         for singleBomb in bombs:
            if (collide_mask(rabbitPlayer, singleBomb)):
               powerupScorebrd.setColour(singleBomb.colour)
               singleBomb.kill()
               rabbitScorebrd.jump = 1
               powerup = BOMB
         for singleExpand in expands:
            if (collide_mask(rabbitPlayer, singleExpand)):
               powerupScorebrd.setColour(singleExpand.colour)
               singleExpand.kill()
               rabbitScorebrd.jump = 1
               powerup = EXPAND
               
         for wall in pygame.sprite.spritecollide(rabbitPlayer, tatemp2, False):
            if (collide_mask(rabbitPlayer, wall) and jump == 0):
               splat.play()
               rabbitPlayer.kill()
               rabbitPlayer = rabbit.Rabbit()
               render.add(rabbitPlayer)
               rabbitScorebrd.lives -= 1
            else:
               if (poweruplimit != 30 and collide_mask(rabbitPlayer, wall)):
                  wall.kill()
               
         for wall in pygame.sprite.spritecollide(masonPlayer, walls, False):
            if (collide_mask(masonPlayer,wall)):
               crash.play()
               wall.kill()
               masonPlayer.kill()
               # masonPlayer = mason.Mason()
               # x = int(SCREENRECT.width * random.random())
               # y = int((SCREENRECT.height  - FONT_SIZE) * random.random())
               # masonPlayer.newXY(x,y)
               # render.add(masonPlayer)
               masonScorebrd.lives -= 1
               
         for wall in pygame.sprite.spritecollide(rabbitPlayer, walls, False):	      
            if (jump == 0):
               if (collide_mask(rabbitPlayer, wall)):
                  splat.play()
                  rabbitPlayer.kill()
                  rabbitPlayer = rabbit.Rabbit()
                  render.add(rabbitPlayer)
                  rabbitScorebrd.lives -= 1
                  powerupScorebrd.setRightPos(rabbitScorebrd.rect.left - 10, rabbitScorebrd.rect.centery)
               
               if (collide_mask(rabbitPlayer,masonPlayer)):
                  splat.play()
                  rabbitPlayer.kill()
                  rabbitPlayer = rabbit.Rabbit()
                  render.add(rabbitPlayer)
                  rabbitScorebrd.lives -= 1
                  powerupScorebrd.setRightPos(rabbitScorebrd.rect.left - 10, rabbitScorebrd.rect.centery)
            elif (jump == 1 and (poweruplimit == 2 or poweruplimit == 60)):
               if (collide_mask(rabbitPlayer, wall)):
                  wall.kill()
		  
         #print poweruplimit  	
         #print jump	  
         if (poweruplimit == 2):      
            if (jump == 1):
               jumpCount += 1
               rabbitPlayer.explode()
               gameMessages = gameMessage.GameMessage()
               gameMessages.isCentre = False
               gameMessages.counter = 5 - jumpCount
               render.add(gameMessages)
         
            if (jumpCount == poweruplimit):
               jumpCount = 0
               jump = 0
               #rabbitPlayer.expand()
               #rabbitPlayer.deflate()
               rabbitPlayer.implode()
               #rabbitPlayer.exploded = 0
               poweruplimit = 0
               if (rabbitScorebrd.jump == 0):
                  powerupScorebrd.setColour(TRANSPARENT)
         elif (poweruplimit == 60):
            if (jump == 1):
               jumpCount += 1
               gameMessages = gameMessage.GameMessage()
               gameMessages.isCentre = False
               gameMessages.counter = 60 - jumpCount
               render.add(gameMessages)
         
            #if (jumpCount == 60):
            if (jumpCount == poweruplimit):
               jumpCount = 0
               jump = 0
               rabbitPlayer.deflate()	
               poweruplimit = 0
               if (rabbitScorebrd.jump == 0):
                  powerupScorebrd.setColour(TRANSPARENT)
         elif (poweruplimit == 30):
            print 'JUMP'
            if (jump == 1):
               jumpCount += 1
               gameMessages = gameMessage.GameMessage()
               gameMessages.isCentre = False
               gameMessages.counter = 30 - jumpCount
               render.add(gameMessages)
         
            #if (jumpCount == 30):
            if (jumpCount == poweruplimit):
               jumpCount = 0
               jump = 0	
               poweruplimit = 0
               if (rabbitScorebrd.jump == 0):
                  powerupScorebrd.setColour(TRANSPARENT)
  
         # update the sprites
         if (trailCounter < 1):
            trailCounter += 1
         else:
            trailCounter = 0
            if (on > 0 and on < 100):
               trailnew = wallSection.WallSection(masonPlayer.rect, masonPlayer.angle)
               tatemp2.add(trailnew)
               #print len(tatemp)
               tatemp[index] = trailnew
               render.add(trailnew)
         
            on += 1
            if (on > 25):
               on = -5
            if (index > 8):
               indexflag = 1
            #print trailnew.rect
            if (indexflag > 0):
               walls.add(tatemp[index2])
               index2 = (index2 + 1) % 10
               #print index
            #print index
            index = (index + 1) % 10
            
         if (masonScorebrd.lives <= 0):
            gameMessages = gameMessage.GameMessage()
            gameMessages.message = 'Opps! The Mason crashed into the wall.'
            render.add(gameMessages)
            # update the sprites
            render.update()

            # draw the scene
            render.clear(screen, background)
            render.draw(screen)
            pygame.display.update()
            
            pause_temp()
            pause_temp()
            gameMessages.kill()
            
            masonDied = True
            break
            
         if (rabbitScorebrd.lives <= 0):
            gameMessages = gameMessage.GameMessage()
            gameMessages.message = 'Opps! The rabbit has no more lives.'
            render.add(gameMessages)
            # update the sprites
            render.update()

            # draw the scene
            render.clear(screen, background)
            render.draw(screen)
            pygame.display.update()
            
            pause_temp()
            pause_temp()
            gameMessages.kill()
            
            masonDied = False
            break
            
         if (len(crops) <= 0):
            rabbitScorebrd.score += timerScorebrd.currentTime
            gameMessages = gameMessage.GameMessage()
            gameMessages.message = 'Oh noes! The rabbit ate all the crops'
            render.add(gameMessages)
            # update the sprites
            render.update()

            # draw the scene
            render.clear(screen, background)
            render.draw(screen)
            pygame.display.update()
            
            pause_temp()
            pause_temp()
            gameMessages.kill()
            
            masonDied = True
            break
            
         
         
         render.update()
         #draw the scene
         render.clear(screen, background)
         render.draw(screen)
         pygame.display.update()
      
      endGameScreen = True
      timerScorebrd.currentRound += 1
      if (not masonDied):
         masonScorebrd.score = rabbitScorebrd.score
         
# run main()
if __name__ == "__main__": main()
